#ifndef SHAREDOUTPUTSTREAMBUFFER_H_JM_20121213
#define SHAREDOUTPUTSTREAMBUFFER_H_JM_20121213

// ## jm4bbx
#include "../../boxes/output/StreamWriterBox.h"
#include "../../common_bbx/mutex/mutex.h"
// ## c++
#include <vector>
#include <string>

namespace jm4bbx {
	/**
	 * Implementacia zdielaneho bufferovaneho vystupneho streamu.
	 * Zdielany = viac dodavatelov dat -> nutna synchronizacia.
	 * Bufferovany = nezapisauje data nikam len do svojho vnutorneho bufferu 
	 * odkial si ich je mozne vybat ako celok.
	 **/
	class SharedOutputStreamBuffer : public StreamWriterBox::OutputStream {
	public:
		/// Data sa budu ukladat po riadkoch v textovej podobe.
		typedef std::vector<std::string> Buffer;
		
		/// Listener umoznujuci nacuvat zatvaraniu vystupov modelu 
		/// dodavajucich data do bufferovaneho streamu.
		struct SharedOutputCloseListener {
			virtual void streamClosed() = 0;
		};

		SharedOutputStreamBuffer() : listener_(nullptr) {	}
		virtual ~SharedOutputStreamBuffer() {}

		/// Otvorenie streamu - pre zdielany bufferobany stream nic zaujimave.
		virtual bool open() { return true; };
		
		/// Zatvorenie streamu - informacia okoliu ze jeden vystupmodelu 
		/// bol zavrety ale stream stale funguje a je schopny prijat data.
		virtual bool close() {
			listener_->streamClosed();
			return true; 
		};

		// Synchronizovany vstup dat/riadku do bufferu.
		virtual OutputStream& operator<<(const std::string& str) {
			{
				Lock<Mutex>::ScopeLock lock(mutex_);
				buffer_.push_back(str);
			}
			return *this;
		}

		void setSharedOutputCloseListener(SharedOutputCloseListener* l) {
			assert(!listener_);
			if (listener_) {
				throw new  std::logic_error("Listener is used by another object!");
			}
			else {
				listener_ = l;
			}
		}

		void reset() {
			listener_ = nullptr;
			buffer_.clear();
		}

		SharedOutputStreamBuffer::Buffer* getBuffer() { return &buffer_; }
	private:
		SharedOutputCloseListener* listener_;
		Buffer buffer_;
		mutable Mutex mutex_;
	};
	
} // namespace jm4bbx

#endif
